/**
 * # Copyright (c) 2009-2010 Beijing RYTong Information Technologies, Ltd.
 * # All rights reserved.
 * #
 * # No part of this source code may be copied, used, or modified
 * # without the express written consent of RYTong.
 */
package com.rytong.tools.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.text.TextUtils;

import com.rytong.tools.utils.Utils;

/**
 * @author Chris
 * 
 *         2009-12-31
 * 
 */
public class CssStyle {
    // 样式控件宽高标志
    final public static String WIDTH = "width";
    final public static String HEIGHT = "height";
    // 背景图样式
    final public static String BGIMAGEURL = "background-image";
    final public static String DISPLAY = "display";
    final public static String ENABLE = "enable";
    final public static String MARGINTOP = "margin-top";
    public static final String FONTSIZE = "font-size";
    public static final String COLOR = "color";
    public static final String LEFT = "left";
    public static final String TOP = "top";
    public static final String RIGHT = "right";
    public static final String BOTTOM = "bottom";
    public static final String TEXT_CENTER = "center";
    public static final String BACKGROUNDCOLOR = "background-color";
    final public static String FONTWEIGHT = "font-weight";
    final public static String TEXTALIGN = "text-align";
    final public static String ALIGN = "align";
    // 渐变样式
    public static final String FILTER = "filter";
    // syle的哈西表
    public static HashMap STYLEHASH;
    // 样式属性存储表，考虑到以后样式扩展，用这个哈西表存储每一对名和值
    private HashMap<String, String> propertyHash_;
    // 记录各样式的相对位置,主要用于解决样式设置冲突问题,哪种效果在最后就实现哪种效果
    private List propertyIndexList_;
    static int NODE = 0;
    static int CLASS = 1;

    static int BORDER_LEFT = 0;
    static int BORDER_TOP = 1;
    static int BORDER_RIGHT = 2;
    static int BORDER_BOTTOM = 3;
    int bottom_;
    int right_;
    /**
     * 只对柱状图或折线图起作用，用于设定纵向刻度轴或横向刻度周的刻度间隔。
     */
    int margintop_;
    // 控件位置是否固定，如果固定，postion的值为fixed，不固定，该值为空
    public String position_;
    // foreground color(RGB). e.g., #ff00ffff
    // background-color(RGB). e.g., #ff00ffff

    public int borderWidth_ = -1;
    public int borderColor_ = Integer.MIN_VALUE;
    int[] borderWidths_;
    int[] borderColors_;
    // String borderStyle_;

    String fontFamily_ = null;

    // 渐变色属性
    public int gradientType = 0;
    public int startColorStr = 0;
    public int endColorStr = 0;
    public float alpha = 0;
    // 记录样式的原始字符串
    public String content_ = "";

    /**
     * 
     */
    public CssStyle() {
        propertyHash_ = new HashMap<String, String>();
    }
    
    public static final void parseStyle(String styleStr) {
        if (styleStr == null || styleStr.trim().equals("")) {
            return;
        }
        // divide the string to style strings, e.g., "xxx{xxx}".
        String[] sepedStr = Utils.string2Array(styleStr, "}");
        if (sepedStr == null) {
            return;
        }
        // dispose each style string.
        int arrStrSize = sepedStr.length;
        CssStyle style = null;
        int selSize = 0;
        String[] styleArr = null;
        if(STYLEHASH == null){
        	STYLEHASH = new HashMap();
        } else {
        	STYLEHASH.clear();
        }
        for (int i = 0; i < arrStrSize; i++) {
            styleArr = Utils.string2Array(sepedStr[i], "{");
            if (styleArr.length != 2) {
                // the array must consist of 2 elements: CSS selector string and
                // value string.
                continue;
            }

            // dispose CSS selectors.
            String[] selectors = Utils.string2Array(styleArr[0], ",");
            if (selectors == null) {
                continue;
            }

//            // dispose values.
//            style = createStyle(styleArr[1]);
//            if (style == null) {
//                continue;
//            }
            // restore styles.
            selSize = selectors.length;
            for (int j = 0; j < selSize; j++) {
                selectors[j] = selectors[j].trim();
                if (selectors[j].startsWith(".")) {
                    // delete the '.' at the front of the class name. e.g.,
                    // .name.
                    // 截取.和{中间的字符串作为样式的名字
                    selectors[j] = selectors[j].substring(1);
                    // dispose values.
                    style = createStyle(selectors[j] , styleArr[1]);
                    if (style == null) {
                        continue;
                    }
                    
                    STYLEHASH.put(selectors[j], style);
                }
            }
        }
//        return styleMap;
    }

    /**
     * @param propertyStr
     * @return
     */
    private static final CssStyle createStyle(String name , String propertyStr) {
    	if (propertyStr == null || propertyStr.trim().equals("") || TextUtils.isEmpty(name)) {
            return null;
        }

        String[] propertyArr = Utils.string2Array(propertyStr, ";");
        if (propertyArr == null) {
            return null;
        }

//        CssStyle cstyle = new CssStyle();
//        cstyle.content_ = propertyStr;
        HashMap<String, String> propertyHash = new HashMap<String, String>();
        List propertyIndexList = new ArrayList<String>();
        // dispose each style value.
        int propertyNum = propertyArr.length;
        String propertyName;
        String propertyValue;
                
        //cstyle 赋值
//        CssStyle cstyle = null;
//        if(STYLEHASH != null && STYLEHASH.containsKey(name)){
//            Object object = STYLEHASH.get(name);
//            if(object != null && object instanceof CssStyle){
//                cstyle = (CssStyle)object;
//            } 
//        }
//        if(cstyle == null){
//            cstyle = new CssStyle();
//        }
        CssStyle cstyle = new CssStyle();
                
        for (int i = 0; i < propertyNum; i++) {
        	boolean flag = true;//是否需要添加
            propertyName = null;
            propertyValue = null;
            int sepIndex = propertyArr[i].indexOf(':');
            if (sepIndex == -1) {
                continue;
            }

            try {
                propertyName = propertyArr[i].substring(0, sepIndex).trim();
                propertyValue = propertyArr[i].substring(sepIndex + 1).trim();
                if(cstyle.propertyHash_ != null && cstyle.propertyHash_.containsKey(propertyName)){
                	flag = false;
                }
            } catch (Exception e1) {
                Utils.printException(e1);
                continue;
            }

            if(flag){
            	    propertyHash.put(propertyName, propertyValue);
            	    propertyIndexList.add(propertyName);
            	    
            	    cstyle.content_ = cstyle.content_ + propertyName + ":" + propertyValue + ";";
            	    
            	    if (propertyName == null || propertyName.equals("")) {
            	        continue;
            	    }
            	
            	    try {
            	
            	        if (propertyName.equalsIgnoreCase(FILTER)) {
            	            // e.g.,progid(GradientType=0, StartColorStr='#63B8FF', EndColorStr="#0000FF")
            	            Object[] properties = getFilterProperty(propertyValue.substring(7, propertyValue.length() - 1));
            	            if (properties == null || properties.length != 4)
            	                continue;
            	            cstyle.gradientType = (Integer) properties[0];
            	            cstyle.startColorStr = (Integer) properties[1];
            	            cstyle.endColorStr = (Integer) properties[2];
            	            cstyle.alpha = (Float) properties[3];
            	        } else if (propertyName.equalsIgnoreCase(BGIMAGEURL)) {
            	            // e.g.,url(/i/eg_bg_03.gif)
            	            propertyHash.put(propertyName, propertyValue.substring(4, propertyValue.length() - 1));
            	        } else if (propertyName.equalsIgnoreCase(COLOR)) {
            	            // e.g.,#00ff00
            	            propertyHash.put(propertyName, propertyValue);
            	        } else if (propertyName.equalsIgnoreCase("border")) {
            	            // e.g., 1px #00ff00 solid
            	            int widthIndex = 0;
            	            int colorIndex = 1;
            	            int[] properties = getBorderProperty(propertyValue);
            	            if (properties == null || properties.length != 2) {
            	                continue;
            	            }
            	            cstyle.borderWidth_ = properties[widthIndex];
            	            cstyle.borderColor_ = properties[colorIndex];
            	        } else if (propertyName.equalsIgnoreCase("border-left")) {
            	            // e.g., 1px #00ff00 solid
            	            int widthIndex = 0;
            	            int colorIndex = 1;
            	            int[] properties = getBorderProperty(propertyValue);
            	            if (properties == null || properties.length != 2) {
            	                continue;
            	            }
            	            initBorderWidth(cstyle);
            	            setBorderWidth(cstyle, properties[widthIndex], BORDER_LEFT);
            	            initBorderColor(cstyle);
            	            setBorderColor(cstyle, properties[colorIndex], BORDER_LEFT);
            	        } else if (propertyName.equalsIgnoreCase("border-top")) {
            	            // e.g., 1px #00ff00 solid
            	            int widthIndex = 0;
            	            int colorIndex = 1;
            	            int[] properties = getBorderProperty(propertyValue);
            	            if (properties == null || properties.length != 2) {
            	                continue;
            	            }
            	            initBorderWidth(cstyle);
            	            setBorderWidth(cstyle, properties[widthIndex], BORDER_TOP);
            	            initBorderColor(cstyle);
            	            setBorderColor(cstyle, properties[colorIndex], BORDER_TOP);
            	        } else if (propertyName.equalsIgnoreCase("border-right")) {
            	            // e.g., 1px #00ff00 solid
            	            int widthIndex = 0;
            	            int colorIndex = 1;
            	            int[] properties = getBorderProperty(propertyValue);
            	            if (properties == null || properties.length != 2) {
            	                continue;
            	            }
            	            initBorderWidth(cstyle);
            	            setBorderWidth(cstyle, properties[widthIndex], BORDER_RIGHT);
            	            initBorderColor(cstyle);
            	            setBorderColor(cstyle, properties[colorIndex], BORDER_RIGHT);
            	        } else if (propertyName.equalsIgnoreCase("border-bottom")) {
            	            // e.g., 1px #00ff00 solid
            	            int widthIndex = 0;
            	            int colorIndex = 1;
            	            int[] properties = getBorderProperty(propertyValue);
            	            if (properties == null || properties.length != 2) {
            	                continue;
            	            }
            	            initBorderWidth(cstyle);
            	            setBorderWidth(cstyle, properties[widthIndex], BORDER_BOTTOM);
            	            initBorderColor(cstyle);
            	            setBorderColor(cstyle, properties[colorIndex], BORDER_BOTTOM);
            	        } else if (propertyName.equalsIgnoreCase("font-family")) {
            	            cstyle.fontFamily_ = propertyValue;
            	        } else if (propertyName.equalsIgnoreCase("position")) {
            	            cstyle.position_ = propertyValue;
            	        } else if (propertyName.equalsIgnoreCase(MARGINTOP)) {
            	            // e.g.,margin-top:40px;
            	            propertyHash.put(propertyName, propertyValue.substring(0, propertyValue.length()));
            	        } else if (propertyName.equalsIgnoreCase(BACKGROUNDCOLOR)) {
            	            // e.g.,background-color:#FFFFFF;
            	            propertyHash.put(propertyName, propertyValue);
            	        } else if (propertyName.equalsIgnoreCase(ALIGN)) {
            	            propertyHash.put(propertyName, propertyValue);
            	        }
            	    } catch (Exception e) {
            	        e.printStackTrace();
            	        continue;
            	    }
            }

        }
        cstyle.setProperty(propertyHash);
        cstyle.setPropertyIndex(propertyIndexList);
        return cstyle;
    }

    private void setPropertyIndex(List propertyIndexList) {
        // TODO Auto-generated method stub
    	if(propertyIndexList_ == null){
    		propertyIndexList_ = new ArrayList<String>();
    	}
    	propertyIndexList_.addAll(propertyIndexList);
    }

    private void setProperty(HashMap<String, String> propertyHash) {
        // TODO Auto-generated method stub
    	if(propertyHash_ == null){
    		propertyHash_ = new HashMap<String, String>();
    	}
    	propertyHash_.putAll(propertyHash);
    }

    public void setProperty(String name, String value) {
        if (null == propertyHash_)
            propertyHash_ = new HashMap<String, String>();
        if(name == null || value == null){
        	return;
        }
        propertyHash_.put(name.trim(), value.trim());
    }

    public String getProperty(String name) {
        if (null == propertyHash_)
            return "";
        return propertyHash_.get(name);
    }

    /**
     * 返回样式设置的最后出现位置
     * 
     * @param name
     * @return
     */
    public int getPropertyIndex(String name) {
        if (null == propertyIndexList_)
            return 0;
        return propertyIndexList_.lastIndexOf(name);
    }

    private static int[] getBorderProperty(String propertyValue) throws Exception {
        int width;
        int color;
        int blankIndex = propertyValue.indexOf(' ');
        if (blankIndex == -1) {
            return null;
        }
        width = Integer.parseInt(Component.fixedPX(propertyValue.substring(0, blankIndex - 2)));

        propertyValue = propertyValue.substring(blankIndex + 1).trim();
        blankIndex = propertyValue.indexOf(' ');
        if (blankIndex == -1) {
            return null;
        }

        color = Utils.getColorValue(propertyValue.substring(0, blankIndex));

        return new int[] { width, color };
    }

    private static Object[] getFilterProperty(String propertyValue) {
        int gradientType = 0;
        int startColorStr = 0;
        int endColorStr = 0;
        float alpha = 0.0f;
        String[] filterProperty = propertyValue.split(",");
        String[] filterStrings = new String[4];
        System.arraycopy(filterProperty, 0, filterStrings, 0, filterProperty.length);
        int size = filterStrings.length;
        for (int i = 0; i < size; i++) {
            if (filterStrings[i] == null || size > 4)
                continue;
            filterStrings[i] = filterStrings[i].trim().toLowerCase();
            if (filterStrings[i].indexOf("gradient") != -1) {
                try {
                    gradientType = Integer.parseInt(filterStrings[i].substring(filterStrings[i].indexOf("=") + 1));
                } catch (Exception e) {
                    Utils.printException(e);
                    gradientType = 0;
                }
            } else if (filterStrings[i].indexOf("start") != -1) {
                String startcolortemp = filterStrings[i].substring(15, filterStrings[i].length() - 1);
                if (startcolortemp != null) {
                    if (startcolortemp.equals("")) {
                        startcolortemp = "#00000000";
                    }
                    startColorStr = Utils.getColorValue(startcolortemp);
                }
            } else if (filterStrings[i].indexOf("end") != -1) {
                String endColorTemp = filterStrings[i].substring(13, filterStrings[i].length() - 1);
                if (endColorTemp != null) {
                    if (endColorTemp.equals("")) {
                        endColorTemp = "#00000000";
                    }
                    endColorStr = Utils.getColorValue(endColorTemp);
                }
//                break;
            } else {
                try {
                    alpha = Float.parseFloat(filterStrings[i].substring(7, filterStrings[i].length() - 1));
                } catch (Exception e) {
                    Utils.printException(e);
                    alpha = 0.0f;
                }
            }
        }
        return new Object[] { gradientType, startColorStr, endColorStr, alpha };
    }

    /**
     * @param cstyle
     * @param color
     * @param dir
     */
    private static void setBorderColor(CssStyle cstyle, int color, int dir) {
        try {
            cstyle.borderColors_[dir] = color;
        } catch (Exception e) {
        }
    }

    /**
     * @param cstyle
     */
    private static void initBorderColor(CssStyle cstyle) {
        if (cstyle.borderColors_ == null) {
            cstyle.borderColors_ = new int[4];
        }
    }

    /**
     * @param cstyle
     * @param width
     * @param dir
     */
    private static void setBorderWidth(CssStyle cstyle, int width, int dir) {
        try {
            cstyle.borderWidths_[dir] = width;
        } catch (Exception e) {
            Utils.printException(e);
        }
    }

    /**
     * @param cstyle
     */
    private static void initBorderWidth(CssStyle cstyle) {
        if (cstyle.borderWidths_ == null) {
            cstyle.borderWidths_ = new int[4];
            cstyle.borderWidths_[BORDER_LEFT] = -1;
            cstyle.borderWidths_[BORDER_TOP] = -1;
            cstyle.borderWidths_[BORDER_RIGHT] = -1;
            cstyle.borderWidths_[BORDER_BOTTOM] = -1;
        }
    }

    public void releaseResource() {
        // TODO Auto-generated method stub
        if (null != propertyHash_ && !propertyHash_.isEmpty())
            propertyHash_.clear();
        propertyHash_ = null;
        if (null != propertyIndexList_ && !propertyIndexList_.isEmpty())
            propertyIndexList_.clear();
        propertyIndexList_ = null;
    }
}
